//
//  XIRuntime.h
//  XI Engine
//
//  Created by Balazs Faludi on 18.06.09.
//  Copyright 2009 Balazs Faludi. All rights reserved.
//

#ifndef XIRuntime_h
#define XIRuntime_h

#import <objc/runtime.h>
#import "NSString+XIExtensions.h"

static inline BOOL setValueOfObjectForPropertyName(NSObject **object, NSString *propertyName, NSObject *value)
{
	@try {
		objc_property_t property = class_getProperty(object_getClass(*object), [propertyName UTF8String]);
		if(property == NULL){return NO;}
		const char *attributes = property_getAttributes(property);
		char encoding = attributes[1];

		NSString *attributesString = [NSString stringWithUTF8String:attributes];
		NSScanner *attributesScanner = [NSScanner scannerWithString:attributesString];
		NSString *setter = @"";
		[attributesScanner scanUpToString:@",S" intoString:nil];
		if([attributesScanner isAtEnd])
		{
			setter = [NSString stringWithFormat:@"set%@:", [propertyName capitalizedFirstCharacter]];
		}
		else
		{
			[attributesScanner scanUpToString:@"," intoString:&setter];
		}
		SEL setterSelector = NSSelectorFromString(setter);

		switch (encoding) {
			case 'B':;  // BOOL
				objc_msgSend(*object, setterSelector, [(NSNumber *)value boolValue]);
				break;
			case 'c':;  // Char
				//objc_msgSend(*object, setterSelector, [(NSNumber *)value charValue]);
				@try {objc_msgSend(*object, setterSelector, [(NSNumber *)value charValue]);}
				@catch (NSException * e) {objc_msgSend(*object, setterSelector, [(NSNumber *)value boolValue]);}
				break;
			case 'd':;  // Double
				objc_msgSend(*object, setterSelector, [(NSNumber *)value doubleValue]);
				break;
			case 'f':;  // Float
				objc_msgSend(*object, setterSelector, [(NSNumber *)value floatValue]);
				break;
			case 'i':;  // Int
				objc_msgSend(*object, setterSelector, [(NSNumber *)value intValue]);
				break;
			case 'l':;  // Long
				objc_msgSend(*object, setterSelector, [(NSNumber *)value longValue]);
				break;
			case 'q':;  // Longlong
				objc_msgSend(*object, setterSelector, [(NSNumber *)value longLongValue]);
				break;
			case 's':;  // Short
				objc_msgSend(*object, setterSelector, [(NSNumber *)value shortValue]);
				break;
			case 'C':;  // Unsigned char
				objc_msgSend(*object, setterSelector, [(NSNumber *)value unsignedCharValue]);
				break;
			case 'I':;  // Unsigned int
				objc_msgSend(*object, setterSelector, [(NSNumber *)value unsignedIntValue]);
				break;
			case 'L':;  // Unsigned long
				objc_msgSend(*object, setterSelector, [(NSNumber *)value unsignedLongValue]);
				break;
			case 'Q':;  // Unsigned long long
				objc_msgSend(*object, setterSelector, [(NSNumber *)value unsignedLongLongValue]);
				break;
			case 'S':;  // Unsigned short
				objc_msgSend(*object, setterSelector, [(NSNumber *)value unsignedShortValue]);
				break;
			case '@':;
				objc_msgSend(*object, setterSelector, value);
				break;
			default:;
				
				setter = [NSString stringWithFormat:@"set%@FromXil:", [propertyName capitalizedFirstCharacter]];
				setterSelector = NSSelectorFromString(setter);
				objc_msgSend(*object, setterSelector, value);
		}
	}
	@catch (NSException * e)
	{
		NSLog(@"Couldn't set object's (%s) property (%@) to new value (%@)", object_getClassName(*object), propertyName, value);
	}
	
	return YES;
}

static inline BOOL performSelectorOfObject(NSObject **object, NSString *selector, NSObject *parameter)
{
	SEL sel = NSSelectorFromString(selector);
	if(sel == (SEL)0){return NO;}
	Method method = class_getInstanceMethod(object_getClass(*object), sel);
	if(method == NULL){return NO;}
	// error excssaejdfgfd
	method_getNumberOfArguments(method) == 0 ? [*object performSelector:sel] : [*object performSelector:sel withObject:parameter];
	return YES;
}

static inline id newObjectWithClassName(NSString *className)
{
	return class_createInstance(objc_getClass([className UTF8String]), 0);
}

#endif


